package cn.tedu.csmall.sso.service.impl;

import cn.tedu.csmall.commons.exception.CoolSharkServiceException;
import cn.tedu.csmall.commons.pojo.admin.dto.AdminAddDTO;
import cn.tedu.csmall.commons.pojo.admin.dto.AdminLoginDTO;
import cn.tedu.csmall.commons.pojo.admin.model.Admin;
import cn.tedu.csmall.commons.pojo.admin.model.AdminRole;
import cn.tedu.csmall.commons.pojo.admin.vo.AdminListVO;
import cn.tedu.csmall.commons.restful.ResponseCode;
import cn.tedu.csmall.commons.utils.JwtUtils;
import cn.tedu.csmall.sso.mapper.AdminMapper;
import cn.tedu.csmall.sso.mapper.AdminRoleMapper;
import cn.tedu.csmall.sso.service.IAdminService;
import cn.tedu.csmall.sso.utils.AdminUserDetails;
import com.alibaba.fastjson.JSON;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;

@Service
@Slf4j
public class AdminServiceImpl implements IAdminService {

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private AdminMapper adminMapper;

    @Autowired
    public AuthenticationManager manager;

    @Autowired
    private AdminRoleMapper adminRoleMapper;

    @Override
    public void addNew(AdminAddDTO adminAddDTO) {
        log.info("开始执行添加Admin的业务");
        //判断用户名和密码是否为null 或者为空串
        if (adminAddDTO.getUsername()==null || adminAddDTO.getUsername()==""||
            adminAddDTO.getPassword()==null || adminAddDTO.getPassword()==""
        ){
            throw new CoolSharkServiceException(ResponseCode.INTERNAL_SERVER_ERROR,"用户名或密码不能为空");
        }
        //判断用户名是否存在
        int count = adminMapper.countByUsername(adminAddDTO.getUsername());
        if (count>0){
            String message="添加管理员失败，用户名【"+adminAddDTO.getUsername()+"】已经被占用了";
            throw new CoolSharkServiceException(ResponseCode.INTERNAL_SERVER_ERROR,message);
        }
        //以上代码都没问题，则执行新增功能
        //对象转换
        Admin admin = new Admin();
        //利用BeanUtils来完成同名属性的赋值
        BeanUtils.copyProperties(adminAddDTO,admin);
        //密码加密
        String encodePassword = passwordEncoder.encode(admin.getPassword());
        admin.setPassword(encodePassword);
        //补全admin中缺少的内容
        admin.setLoginCount(0);
        admin.setLastLoginIp(null);
        admin.setGmtCreate(LocalDateTime.now());
        admin.setGmtModified(LocalDateTime.now());
        //调用insert完成新增功能
        int row = adminMapper.insert(admin);
        //判断是否新增成功,如果==0，表示插入失败
        if (row==0){
            throw new CoolSharkServiceException(ResponseCode.INTERNAL_SERVER_ERROR,"添加管理员失败！！！");
        }
        LocalDateTime now = LocalDateTime.now();
        AdminRole adminRole = new AdminRole();
        adminRole.setAdminId(admin.getId());
        adminRole.setRoleId(2l);
        adminRole.setGmtCreate(now);
        adminRole.setGmtModified(now);
        row = adminRoleMapper.insert(adminRole);
        if (row<1){
            throw new CoolSharkServiceException(ResponseCode.INTERNAL_SERVER_ERROR,"添加管理员失败，请至少选择一个角色");
        }

    }

    @Override
    public List<AdminListVO> list() {
        log.info("开始处理查询管理员列表的业务");
        return adminMapper.list();
    }

    @Override
    public String login(AdminLoginDTO adminLoginDTO) {
        log.info("开始执行管理员的登陆业务，参数：{}",adminLoginDTO);
        //调用AuthenticationManager执行Spring Security的认证
        Authentication authentication=new UsernamePasswordAuthenticationToken(
                adminLoginDTO.getUsername(),adminLoginDTO.getPassword()
        );
        //调用authenticate方法，该方法如果用户名和密码不匹配会抛出异常，不再往下执行
        Authentication authenticate = manager.authenticate(authentication);
        //从认证结果中获取Principal，本质上就是USER类型，是UserDetailService中loadUserByUser()返回的结果
        log.info("Principal：{}", authenticate.getPrincipal());
        AdminUserDetails user =(AdminUserDetails) authenticate.getPrincipal();
        //用户id
        Long id = user.getId();
        log.info("获取到的用户id为：{}",id);
        //用户名
        String username = user.getUsername();
        log.info("登陆成功的用户名：{}",username);
        //用户权限列表
        Collection<GrantedAuthority> authorities = user.getAuthorities();
        log.info("登陆成功的用户权限列表：{}",authorities);
        String jsonString = JSON.toJSONString(authorities);

        Map claims=new HashMap();
        claims.put("id",id);
        claims.put("username",username);
        claims.put("authorities",jsonString);

        String jwt = JwtUtils.generate(claims);
        log.info("生成JWT数据：{}",jwt);
        return jwt;
    }
}
